package com.yanqu.road.server.manager.beautyescort;

import com.yanqu.road.entity.beautyescort.EscortServerGroup;
import com.yanqu.road.entity.beautyescort.rank.EscortWeekRewardInfo;
import com.yanqu.road.entity.beautyescort.rank.EscortWeekServerGroup;
import com.yanqu.road.entity.enums.eSystemId;
import com.yanqu.road.entity.rank.cross.CrossUnionWeekRank;
import com.yanqu.road.entity.servercenter.ServerInfo;
import com.yanqu.road.logic.bussiness.beautyescort.BeautyEscortBussiness;
import com.yanqu.road.logic.bussiness.rank.RankBussiness;
import com.yanqu.road.logic.config.GameConfig;
import com.yanqu.road.logic.config.beautyescort.BeautyEscortConfig;
import com.yanqu.road.server.manger.ConfigMgr;
import com.yanqu.road.utils.YanQuMessageUtils;
import com.yanqu.road.pb.cross.group.CrossGroupProto;
import com.yanqu.road.server.TempMgr;
import com.yanqu.road.server.logic.MessageHelper;
import com.yanqu.road.server.manger.EscortServerGroupMgr;
import com.yanqu.road.server.manger.ServerListMgr;
import com.yanqu.road.server.manger.plugin.ManagerReloadListener;
import com.yanqu.road.message.YanQuMessage;
import com.yanqu.road.server.protocol.Protocol;
import com.yanqu.road.utils.ConfigHelper;
import com.yanqu.road.utils.date.DateHelper;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

public class CrossBeautyEscortRankMgr extends TempMgr {

    //weekId groupId
    static Map<Integer, Map<Integer, EscortWeekServerGroup>> weekServerGroupMap = new ConcurrentHashMap<>();          //每周区服分组

    //weekId groupId
    private static Map<Integer, Map<Integer, CrossGroupWeekUnionRankListModel>> groupWeekRankListModelMap = new ConcurrentHashMap<>();

    static List<EscortWeekRewardInfo> rankRewardList;

    static List<EscortWeekRewardInfo> rankCrossServerRewardList;

    @Override
    public boolean reloadConfig() throws Exception {
        int preWeekId = getPreWeekId();
        int thisWeekId = getThisWeekId();
        //区服奖励
        List<EscortWeekRewardInfo> tempRankRewardList = BeautyEscortConfig.initRankRewardInfo(GameConfig.ESCORT_WEEK_RANK_REWARD);
        if(tempRankRewardList == null){
            return false;
        }

        //跨服奖励
        List<EscortWeekRewardInfo> crossTempRankRewardList = BeautyEscortConfig.initRankRewardInfo(GameConfig.ESCORT_CROSS_SERVER_WEEK_RANK_REWARD);
        if(crossTempRankRewardList == null){
            return false;
        }

        rankRewardList = tempRankRewardList;

        rankCrossServerRewardList = crossTempRankRewardList;
        return true;
    }

    @Override
    public boolean reloadData() throws Exception {
        int preWeekId = getPreWeekId();
        int thisWeekId = getThisWeekId();
        //数据加载
        weekServerGroupMap = BeautyEscortBussiness.getEscortWeekServerGroup(preWeekId, thisWeekId);

        groupWeekRankListModelMap = new ConcurrentHashMap<>();
        initCrossRankListModelMap(preWeekId, thisWeekId);
        return true;
    }

    @Override
    public boolean init() throws Exception {
        addServerGroupReloadListener();
        return reload();
    }

    private void addServerGroupReloadListener(){
        EscortServerGroupMgr.addReloadListener(new ManagerReloadListener() {
            @Override
            public void notifyReload() {
                serverGroupReload();
                notifyServerReload();
            }
        });
    }

    @Override
    public boolean stop() {
        return false;
    }

    @Override
    public boolean save() {

        for (Map.Entry<Integer, Map<Integer, EscortWeekServerGroup>> mapEntry : weekServerGroupMap.entrySet()) {
            for (Map.Entry<Integer, EscortWeekServerGroup> groupEntry : mapEntry.getValue().entrySet()) {
                if(groupEntry.getValue().isInsertOption()){
                    BeautyEscortBussiness.addEscortWeekServerGroup(groupEntry.getValue());
                }else if(groupEntry.getValue().isUpdateOption()){
                    BeautyEscortBussiness.updateBeautyEscortBussiness(groupEntry.getValue());
                }
            }
        }

        for (Map.Entry<Integer, Map<Integer, CrossGroupWeekUnionRankListModel>> weekGroupMapEntry : groupWeekRankListModelMap.entrySet()) {
            for (Map.Entry<Integer, CrossGroupWeekUnionRankListModel> modelEntry : weekGroupMapEntry.getValue().entrySet()) {
                modelEntry.getValue().saveRankList();
            }
        }
         return true;
    }

    private void initCrossRankListModelMap(int preWeekId, int thisWeekId) {
        Map<Integer, Map<Integer, LinkedList<CrossUnionWeekRank>>> tempDbMap = RankBussiness.getEscortWeekRankListModelMap(preWeekId,thisWeekId);
        synchronized (groupWeekRankListModelMap) {
            for (Map.Entry<Integer, Map<Integer, LinkedList<CrossUnionWeekRank>>> weekMapEntry : tempDbMap.entrySet()) {
                for (Map.Entry<Integer, LinkedList<CrossUnionWeekRank>> listEntry : weekMapEntry.getValue().entrySet()) {
                    CrossGroupWeekUnionRankListModel listModel = new CrossGroupWeekUnionRankListModel(listEntry.getKey(), weekMapEntry.getKey());
                    int rankNum = getMaxRankNum();
                    if(rankNum > 0){
                        listModel.setRankNum(rankNum);
                    }else {
                        listModel.setRankNum(GameConfig.RANK_DEFAULT_MAX_COUNT);
                    }
                    listModel.setRankList(listEntry.getValue());

                    if(!groupWeekRankListModelMap.containsKey(weekMapEntry.getKey())){
                        groupWeekRankListModelMap.put(weekMapEntry.getKey(), new ConcurrentHashMap<>());
                    }
                    if(!groupWeekRankListModelMap.get(weekMapEntry.getKey()).containsKey(listEntry.getKey())){
                        groupWeekRankListModelMap.get(weekMapEntry.getKey()).put(listEntry.getKey(), listModel);
                    }
                }
            }
        }
    }

    /**
     * 获取榜单最大长度
     */
    public static int getMaxRankNum(){
        int max = 0;
        for (EscortWeekRewardInfo rewardInfo : rankRewardList) {
            if(rewardInfo.getMax() > max){
                max = rewardInfo.getMax();
            }
        }
        return max;
    }

    /**
     * 获取榜单最大长度(跨服)
     */
    public static int getMaxCrossServerRankNum(){
        int max = 0;
        for (EscortWeekRewardInfo rewardInfo : rankCrossServerRewardList) {
            if(rewardInfo.getMax() > max){
                max = rewardInfo.getMax();
            }
        }
        return max;
    }

    /**
     * 获取榜单奖励
     */
    public static EscortWeekRewardInfo getRankReward(int rank){
        for (EscortWeekRewardInfo rewardInfo : rankRewardList) {
            if(rank >= rewardInfo.getMin() && rank <= rewardInfo.getMax()){
                return rewardInfo;
            }
        }
        if(rank == -1){
            return null;
        }
        return getRankReward(-1);
    }

    /**
     * 更新榜单
     */
    public static void changeUnionRank(int weekId, long serverId, CrossUnionWeekRank unionWeekRank) {
        int groupId = getGroupId(serverId);
        //getLogger().debug("weekI,groupId,unionUid,value:{},{},{},{}", weekId, groupId, unionWeekRank.getUnionUid(), unionWeekRank.getValue().toString());
        CrossGroupWeekUnionRankListModel rankListModel = getCrossGroupWeekUnionRankListModel(weekId, groupId);
        if(rankListModel == null){
            synchronized (groupWeekRankListModelMap){
                rankListModel = getCrossGroupWeekUnionRankListModel(weekId, groupId);
                if(rankListModel == null){
                    if(!groupWeekRankListModelMap.containsKey(weekId)){
                        groupWeekRankListModelMap.put(weekId, new ConcurrentHashMap<>());
                    }
                    if(!groupWeekRankListModelMap.get(weekId).containsKey(groupId)){
                        rankListModel = new CrossGroupWeekUnionRankListModel(groupId, weekId);
                        groupWeekRankListModelMap.get(weekId).put(groupId, rankListModel);
                    }
                }
            }
            rankListModel = getCrossGroupWeekUnionRankListModel(weekId, groupId);
        }
        if(rankListModel != null){
            rankListModel.rankChange(unionWeekRank);
        }
    }

    public static CrossGroupWeekUnionRankListModel getCrossGroupWeekUnionRankListModel(int weekId, int groupId){
        if (!groupWeekRankListModelMap.containsKey(weekId)) {
            return  null;
        }
        return groupWeekRankListModelMap.get(weekId).get(groupId);
    }

    public static int getGroupId(long serverId) {
        EscortServerGroup serverGroup = EscortServerGroupMgr.getServerGroupByServerId(serverId);
        if(serverGroup != null && serverGroup.getEscortState() == 1){
            return serverGroup.getGroupId();
        }
        return (int)serverId;
    }

    /**
     * 本周id
     */
    public static int getThisWeekId(){
        Calendar now = Calendar.getInstance();
        //如果是周天
        if(now.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY){
            long zeroTime = DateHelper.getTodayZeroTimeStamp();
            //22点后，返回后一天零点
            if(now.getTimeInMillis() >= (zeroTime + ConfigMgr.getEscortingEndMinute() * 60 * 1000)){
                now.setTimeInMillis(zeroTime);
                now.add(Calendar.HOUR, 24);
            }else {
                Date monday = DateHelper.getThisWeekMonday(now.getTime());
                now.setTime(monday);
            }
        }else {
            Date monday = DateHelper.getThisWeekMonday(now.getTime());
            now.setTime(monday);
        }
        return Integer.valueOf(DateHelper.getPyyyyMMddDateString(now.getTimeInMillis() / 1000));
    }

    /**
     * 获取所在组的区服列表(没有分组即独自成组)
     */
    public static Set<Long> getGroupServer(int groupId){
        Set<Long> serverSet = new HashSet<>();
        EscortServerGroup serverGroup = EscortServerGroupMgr.getServerGroup(groupId);
        if(serverGroup == null || serverGroup.getEscortState() == 0){
            serverSet.add((long)groupId);
        }else{
            serverSet.addAll(serverGroup.getServerList());
        }
        return serverSet;
    }

    /**
     * 获取所在组的区服列表(没有分组即独自成组)
     */
    public static List<Long> getGroupServer(long serverId){
        List<Long> serverList = new ArrayList<>();
        EscortServerGroup serverGroup = EscortServerGroupMgr.getServerGroupByServerId(serverId);
        if(serverGroup == null || serverGroup.getEscortState() == 0){
            serverList.add(serverId);
        }else{
            serverList.addAll(serverGroup.getServerList());
        }
        return serverList;
    }

    /**
     * 前一周id
     */
    public static int getPreWeekId() {
        Calendar now = Calendar.getInstance();
        //如果是周天
        if(now.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY){
            long zeroTime = DateHelper.getTodayZeroTimeStamp();
            //22点后，返回本周零点
            if(now.getTimeInMillis() >= (zeroTime + ConfigMgr.getEscortingEndMinute() * 60 * 1000)){
                Date monday = DateHelper.getThisWeekMonday(now.getTime());
                now.setTime(monday);
            }else {
                Date monday = DateHelper.getThisWeekMonday(now.getTime());
                now.setTime(monday);
                now.add(Calendar.HOUR, -7 * 24);
            }
        }else {
            Date monday = DateHelper.getThisWeekMonday(now.getTime());
            now.setTime(monday);
            now.add(Calendar.HOUR, -7 * 24);
        }
        return Integer.valueOf(DateHelper.getPyyyyMMddDateString(now.getTimeInMillis() / 1000));
    }

    /**
     * 过期数据移除
     */
    public static void removeOutTimeData(){
        Calendar now = Calendar.getInstance();
        now.add(Calendar.MONTH, -1);
        int monthBefore = Integer.valueOf(DateHelper.getPyyyyMMddDateString(now.getTimeInMillis() / 1000));

        for (Map.Entry<Integer, Map<Integer, CrossGroupWeekUnionRankListModel>> weekEntry : groupWeekRankListModelMap.entrySet()) {
            if(weekEntry.getKey() < monthBefore){
                synchronized (groupWeekRankListModelMap){
                    groupWeekRankListModelMap.remove(weekEntry.getKey());
                }
            }
        }

        for (Map.Entry<Integer, Map<Integer, EscortWeekServerGroup>> entry : weekServerGroupMap.entrySet()) {
            if(entry.getKey() < monthBefore){
                synchronized (weekServerGroupMap){
                    weekServerGroupMap.remove(entry.getKey());
                }
            }
        }
    }

    /**
     * 获取上周区服分组
     */
    public static int getWeekServerGroup(int weekId, long serverId){
        if(!weekServerGroupMap.containsKey(weekId)){
            return (int)serverId;
        }
        Map<Integer, EscortWeekServerGroup> serverGroupMap = weekServerGroupMap.get(weekId);
        for (Map.Entry<Integer, EscortWeekServerGroup> groupEntry : serverGroupMap.entrySet()) {
            if(groupEntry.getValue().getServerList().contains(serverId)){
                return groupEntry.getKey();
            }
        }
        return (int)serverId;
    }

    /**
     * 锁定每周区服分组
     */
    public static void lockPreWeekServerGroup(){
        int preWeekId = getPreWeekId();
        if(!weekServerGroupMap.containsKey(preWeekId)){
            Map<Integer, EscortWeekServerGroup> serverGroupMap = new ConcurrentHashMap<>();
            List<EscortServerGroup> serverGroupList = EscortServerGroupMgr.getServerGroupList(ConfigHelper.getInt("channelId"));
            for (EscortServerGroup serverGroup : serverGroupList) {
                EscortWeekServerGroup weekServerGroup = new EscortWeekServerGroup();
                weekServerGroup.setGroupId(serverGroup.getGroupId());
                weekServerGroup.setWeekId(preWeekId);
                for(long sid : serverGroup.getServerList()) {
                    weekServerGroup.getServerList().add(sid);
                }
                weekServerGroup.setInsertOption();
                serverGroupMap.put(serverGroup.getGroupId(), weekServerGroup);
            }
            weekServerGroupMap.put(preWeekId, serverGroupMap);
        }
    }

    public static void serverGroupReload() {
        //区服重载，排行榜重新分组
        int thisWeekId = getThisWeekId();
        if(!groupWeekRankListModelMap.containsKey(thisWeekId)){
            return;
        }
        Map<Integer, CrossGroupWeekUnionRankListModel> groupUnionRankListModelMap = groupWeekRankListModelMap.get(thisWeekId);
        LinkedList<CrossUnionWeekRank> crossUnionRanks = new LinkedList<>();
        synchronized (groupWeekRankListModelMap) {
            for (int groupId : groupUnionRankListModelMap.keySet()) {
                CrossGroupWeekUnionRankListModel unionRankListModel = groupUnionRankListModelMap.get(groupId);
                Set<Long> serverIdSet = getGroupServer(groupId);
                if(serverIdSet.contains((long)groupId) && getGroupId((long)groupId) != groupId){  //本服->跨服
                    crossUnionRanks.addAll(unionRankListModel.removeRank(new HashSet<>()));
                }else {  //区服范围变更
                    crossUnionRanks.addAll(unionRankListModel.removeRank(serverIdSet));
                }
            }
        }
        for(CrossUnionWeekRank unionRank : crossUnionRanks){
            changeUnionRank(thisWeekId, unionRank.getServerId(), unionRank);
        }
    }

    private static void notifyServerReload(){
        List<ServerInfo> serverInfoList = ServerListMgr.getOpenServerList();
        int channelId = ConfigHelper.getInt("channelId");
        CrossGroupProto.SystemServerGroupReloadNotifyMsg.Builder msg = CrossGroupProto.SystemServerGroupReloadNotifyMsg.newBuilder();
        msg.setSystemId(eSystemId.BeautyEscort.getValue());
        YanQuMessage pbMsg = YanQuMessageUtils.buildMessage(Protocol.S_CROSS_SERVER_GROUP_RELOAD_NOTIFY_SYSTEM, msg);
        for(ServerInfo serverInfo : serverInfoList){
            if(serverInfo.getChannelId() == channelId){
                MessageHelper.sendPacket(serverInfo.getServerId(), 0, pbMsg);
            }
        }
    }
}
